package com.morty.config;

import org.apache.http.HttpHost;
import org.apache.http.auth.AuthScope;
import org.apache.http.auth.UsernamePasswordCredentials;
import org.apache.http.client.CredentialsProvider;
import org.apache.http.impl.client.BasicCredentialsProvider;
import org.apache.http.impl.nio.client.HttpAsyncClientBuilder;
import org.apache.http.nio.conn.ssl.SSLIOSessionStrategy;
import org.elasticsearch.client.RestClient;
import org.elasticsearch.client.RestClientBuilder;
import org.elasticsearch.client.RestHighLevelClient;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.stereotype.Component;

import javax.net.ssl.*;
import java.security.KeyManagementException;
import java.security.NoSuchAlgorithmException;
import java.security.SecureRandom;
import java.security.cert.CertificateException;
import java.security.cert.X509Certificate;

/**
 * @Description:
 */

@Component
public class ESClientBuilder {



	@Value("${spring.elasticsearch.cluster_host}")
	private String cluster_host;
	@Value("${spring.elasticsearch.cluster_port}")
	private Integer cluster_port;
	@Value("${spring.elasticsearch.username}")
	private String username;
	@Value("${spring.elasticsearch.password}")
	private String password;
	@Value("${spring.elasticsearch.protocol}")
	private String protocol;

	static TrustManager[] trustAllCerts = new TrustManager[] { new X509TrustManager() {
		@Override
		public void checkClientTrusted(X509Certificate[] chain, String authType) throws CertificateException {

		}
		@Override
		public void checkServerTrusted(X509Certificate[] chain, String authType) throws CertificateException {

		}
		@Override
		public X509Certificate[] getAcceptedIssuers() {
			return null;
		}
	}};

	public static class NullHostNameVerifier implements HostnameVerifier {
		@Override
		public boolean verify(String arg0, SSLSession arg1) {
			return true;
		}
	}

	@Bean
	public RestHighLevelClient getEsClient() {
		if("https".equals(protocol)){
			//Elasticsearch集群需要basic auth验证。
			final CredentialsProvider credentialsProvider = new BasicCredentialsProvider();
			//访问用户名和密码,创建Elasticsearch实例时设置的用户名和密码
			credentialsProvider.setCredentials(AuthScope.ANY, new UsernamePasswordCredentials(this.username, this.password));
			SSLContext sc = null;
			try{
				sc = SSLContext.getInstance("SSL");
				sc.init(null, trustAllCerts, new SecureRandom());
			}catch(KeyManagementException e){
				e.printStackTrace();
			}catch(NoSuchAlgorithmException e){
				e.printStackTrace();
			}
			SSLIOSessionStrategy sessionStrategy = new SSLIOSessionStrategy(sc, new NullHostNameVerifier());
			RestClientBuilder builder = RestClient.builder(new HttpHost(this.cluster_host, this.cluster_port,"https"))
					.setHttpClientConfigCallback(new RestClientBuilder.HttpClientConfigCallback() {
						@Override
						public HttpAsyncClientBuilder customizeHttpClient(HttpAsyncClientBuilder httpClientBuilder) {
							// enable SSL / TLS
							httpClientBuilder.setSSLStrategy(sessionStrategy);
							// enable user authentication
							if (credentialsProvider != null) {
								httpClientBuilder.setDefaultCredentialsProvider(credentialsProvider);
							}
							return httpClientBuilder;
						}
					});
			// RestHighLevelClient实例通过REST low-level client builder进行构造。
			RestHighLevelClient highClient = new RestHighLevelClient(builder);
			return highClient;
		}else{
			RestHighLevelClient highClient = new RestHighLevelClient(RestClient.builder( new HttpHost(cluster_host, cluster_port, protocol)));
			return highClient;
		}
	}
}
